package cc.shacocloud.redis.study.util.codeBlock;

import org.jetbrains.annotations.NotNull;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.function.Function;

/**
 * md文件的代码块解析器
 *
 * @see #parser(BufferedReader)
 */
public class CodeBlockMDParser {

    private static final Function<String, Boolean> sqlIdSymbolFunc = line -> line.startsWith("#");
    private static final Function<String, Boolean> sqlSymbolFunc = line -> line.startsWith("```") || line.startsWith("~~~");
    protected static final String lineSeparatorSymbol = System.getProperty("line.separator", "\n");
    private static final Function<String, String> sqlIdFunc = line -> line.replace("#", "").trim();

    /**
     * @see #parser(BufferedReader)
     */
    @NotNull
    public static Map<String, String> parser(@NotNull File file) throws IOException {
        return parser(new BufferedReader(new FileReader(file)));
    }

    @NotNull
    public static String parser(@NotNull BufferedReader reader, String id) throws IOException {
        return parser(reader).get(id);
    }

    /**
     * 解析sql markdown文件
     * <p>
     * 文档格式：
     * {@code #}符号行为Id行，解析方法： 去除{@code #}符号，在去除前后的空格，剩余的为 Id
     * <p>
     * {@code ```} 或者 {@code ~~~} 符号行为代码块，包含在内的为代码块，
     * 解析方式：上下两个 {@code ```} 或者 {@code ~~~} 符号行中间的为代码块
     * <p>
     * 其他不解析，直接抛弃
     * <p>
     * 例：
     * <pre>
     * # getUserById
     * > 根据用户id查询用户信息
     * ```sql
     * SELECT * FROM `user` WHERE user_id = ?
     * ```
     *
     * # getAllUser
     * > 查询所有用户信息
     * ```sql
     * SELECT * FROM `user`
     * ```
     * </pre>
     *
     * @param reader {@linkplain BufferedReader}
     * @return 解析结果 key-> Id, value-> 代码块
     * @throws IOException 文件读取异常
     */
    @NotNull
    public static Map<String, String> parser(@NotNull BufferedReader reader) throws IOException {
        try (BufferedReader br = reader) {
            Map<String, String> sqlMap = new HashMap<>();
            String sqlId = null;
            StringBuilder builder = null;
            boolean start = false;
            while (true) {
                String line = br.readLine();
                if (line == null) break;

                if (sqlIdSymbolFunc.apply(line)) {
                    sqlId = sqlIdFunc.apply(line);
                    builder = new StringBuilder();
                    continue;
                }

                // ``` ~~~ 为md的代码块，解析其中的内容
                if (sqlSymbolFunc.apply(line) && sqlId != null) {
                    if (start) {
                        sqlMap.put(sqlId, builder.toString());
                        start = false;
                        sqlId = null;
                        builder = null;
                    } else start = true;
                    continue;
                }

                if (start) {
                    builder.append(line).append(lineSeparatorSymbol);
                }
            }

            return sqlMap;
        }
    }

}
